#include "Ly_influence_area.h"
#include "xVMRelationStruct.h"
#include <algorithm>
int max_level;

Ly_influence_area::Ly_influence_area(DIVA_VM* root, bool bRefIn, bool bRefOut, string valNames, int level){
	max_level = level;
	if(bRefOut==true)
		addRefOutLinksToArea(root, valNames, 0);
	if(bRefIn==true)
		addRefInLinksToArea(root, valNames, 0);
}

vector<DIVA_VM*> Ly_influence_area::getVMsLinkedByVM(DIVA_VM* vm){
	vector<DIVA_VM*> ret;
	DIVA_VM* p;
	multimap<DIVA_VM*,DIVA_VM*>::iterator itr;

	vm = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(vm);

	for(itr = _links.begin();itr!=_links.end();itr++){
		p = itr->first;
		if(p == vm)
			ret.push_back(itr->second);
	}

	return ret;
}

vector<DIVA_VM*> Ly_influence_area::getVMsLinkToVM(DIVA_VM* vm){
	vector<DIVA_VM*> ret;
	DIVA_VM* p;
	multimap<DIVA_VM*,DIVA_VM*>::iterator itr;

	vm = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(vm);

	for(itr = _links.begin();itr!=_links.end();itr++){
		p = itr->second;
		if(p == vm)
			ret.push_back(itr->first);
	}

	return ret;
}

void Ly_influence_area::addRefOutLinksToArea(DIVA_VM* root, string valNames, int level_count){
	DIVA_VM* vm;
	vector<DIVA_VM*> tmpVms;
	vector<DIVA_VM*>::iterator itr;
	DIVA_VM* p;

	vm = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(root);
	if(vm->getVMType() == "reference") return;//add by hyt , 權宜之計
	addVMtoRecord(vm);

	tmpVms = xVMRelationStruct::getInstance()->VMRS_nextVMsByRef(vm,valNames);
	if(tmpVms.empty()==true) return;
	/*以中序建立link*/
	for (itr = tmpVms.begin(); itr != tmpVms.end(); itr++) {
		p = (*itr);
		p = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(p);

		if(_links.find(vm)!=_links.end() && _links.find(vm)->second == p) return; 
		if(level_count>=max_level && max_level!=0) return;
		if(p->getVMType() == "reference") return;//add by hyt , 權宜之計
		_links.insert(make_pair(vm,p));
		addRefOutLinksToArea(p, valNames, level_count+1);
	}
}

void Ly_influence_area::addRefInLinksToArea(DIVA_VM* root, string valNames, int level_count){
	DIVA_VM* vm;
	vector<DIVA_VM*> tmpVms;
	vector<DIVA_VM*>::iterator itr;
	DIVA_VM* p;

	vm = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(root);
	if(vm->getVMType() == "reference") return;//add by hyt , 權宜之計
	addVMtoRecord(vm);

	tmpVms = xVMRelationStruct::getInstance()->VMRS_preVMsByRef(vm,valNames);
	if(tmpVms.empty()==true) return;
	for (itr = tmpVms.begin(); itr != tmpVms.end(); itr++) {
		p = (*itr);
		p = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM(p);

		if(_links.find(vm)!=_links.end() && _links.find(vm)->second == p) return; 
		if(level_count>=max_level && max_level!=0) return;
		if(p->getVMType() == "reference") return;//add by hyt , 權宜之計
		_links.insert(make_pair(vm,p));
		addRefInLinksToArea(p, valNames, level_count+1);
	}
}

void Ly_influence_area::addVMtoRecord(DIVA_VM* vm){
	vector<DIVA_VM*>::iterator it;
	it = find(_vms.begin(),_vms.end(),vm);
	if(it != _vms.end()){
		return;
	}
	else{
		_vms.push_back(vm);
	}
}